package com.sharelords.biz.creator;

import com.sharelords.biz.config.GeneralBizConfig;
import com.sharelords.biz.creator.memory.MemoryClassLoader;
import com.sharelords.biz.join.FileContentJoin;
import com.sharelords.biz.util.BizGenericsUtil;
import org.apache.commons.lang.StringUtils;

import javax.tools.JavaFileObject;
import java.io.File;
import java.io.FileWriter;
import java.text.MessageFormat;
import java.util.logging.Logger;

/**
 * @author 千古龙少
 * @Description: class文件生成器
 * @date 2019年9月7日 下午7:35:26
 */
public class ClassCreator {

    private static final Logger logger = Logger.getLogger("ClassCreator");

    private static final String DEF_TEMP_DIR_PATH = System.getProperty("user.dir") + "/../";

    private static final String JAVA_FILE_PATH = "bizTempJavaFile/{0}";

    /**
     * java文件全路径
     */
    private static String JAVA_FILE_REAL_PATH = DEF_TEMP_DIR_PATH + JAVA_FILE_PATH;

    /**
     * 加载配置
     */
    private static final GeneralBizConfig CONFIG = GeneralBizConfig.getInstance();

    private ClassCreator() {
    }

    /**
     * @param clazz Biz接口的子接口class
     * @Description: 创建class文件
     * @author 千古龙少
     * @date 2019年9月7日 下午7:15:12
     */
    public static void createClassFile(Class<?> clazz) {
        if (clazz == null) {
            return;
        }
        if (StringUtils.isNotBlank(CONFIG.srcFilePath)) {
            JAVA_FILE_REAL_PATH = CONFIG.srcFilePath + JAVA_FILE_PATH;
        }

        BizGenericsUtil genericsUtil = new BizGenericsUtil(clazz);
        Class<?> boClass = genericsUtil.getBoClass();
        Class<?> entityClass = genericsUtil.getEntityClass();
        Class<?> dClass = genericsUtil.getdClass();
        Class<?> daoClass = genericsUtil.getDaoClass();

        Class<?>[] arr = new Class<?>[]{boClass, entityClass, dClass, daoClass};

        FileContentJoin fileContentJoin = new FileContentJoin(clazz);
        String fileName = fileContentJoin.getImplClassName();

        // 文件内容组装
        String fileSrc = fileContentJoin
                .imports(arr)
                .generics(arr)
                .autowired(daoClass)
                .methods(clazz, boClass)
                .getResult();

        if (CONFIG.remainJavaSrcFile) {
            // 保留java源文件
            createJavaSrcFile(fileSrc, fileName);
        }

        // 创建class内存文件
        createClassFile(fileSrc, fileName);
    }

    /**
     * @param fileSrc  文件体内容
     * @param fileName 文件名
     * @Description: 创建java源文件
     * @author 千古龙少
     * @date 2019年9月7日 下午7:15:12
     */
    private static void createJavaSrcFile(String fileSrc, String fileName) {
        String filePathFullName = MessageFormat.format(JAVA_FILE_REAL_PATH, fileName) + JavaFileObject.Kind.SOURCE.extension;
        // 生成临时文件
        File file = new File(filePathFullName);
        // 文件路径不存在就创建
        File fileParent = file.getParentFile();
        if (!fileParent.exists()) {
            boolean mkdirFlag = fileParent.mkdirs();
            if (!mkdirFlag) {
                logger.warning("创建[" + filePathFullName + "]对应文件夹失败！");
                return;
            }
        }

        // 生成java文件
        try (FileWriter fileWriter = new FileWriter(file)) {
            fileWriter.write(fileSrc);
            fileWriter.flush();
        } catch (Exception e) {
            logger.warning("获取[" + fileName + ".java]的class文件发生异常" + e.toString());
        }
    }

    /**
     * @param fileSrc  文件体内容
     * @param fileName 文件名
     * @Description: 创建class文件
     * @author 千古龙少
     * @date 2020年6月14日 下午7:15:12
     */
    private static void createClassFile(String fileSrc, String fileName) {
        try {
            // 编译成class文件
            MemoryClassLoader loader = MemoryClassLoader.getInstance();
            loader.registerJava(fileName, fileSrc);
            logger.info("[" + fileName + "]的class文件加载完成");
        } catch (Exception e) {
            logger.warning("获取[" + fileName + ".java]的class文件发生异常" + e.toString());
        }
    }

}
